/**
 * $Id: CMPPMTConnector.java,v 1.4 2006/07/17 09:58:00 star Exp $
 *
 * Copyright 2006 Skyinfo, Inc. All Rights Reserved.
 */
package com.haoxi.gateway.connector.impl;

import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.haoxi.gateway.cmpp30msg.CMPPActiveTest;
import com.haoxi.gateway.cmpp30msg.CMPPActiveTestRep;
import com.haoxi.gateway.cmpp30msg.CMPPConnect;
import com.haoxi.gateway.cmpp30msg.CMPPConnectRep;
import com.haoxi.gateway.cmpp30msg.CMPPMsgHead;
import com.haoxi.gateway.cmpp30msg.CMPPTerminateRep;
import com.haoxi.gateway.cmpp30msg.CMPPCommon;
import com.haoxi.gateway.common.CommonMsgBean;
//import com.haoxi.gateway.common.SYSConst;
import com.haoxi.gateway.connector.Connector;
import com.haoxi.gateway.runner.RunnerMgr;

/**
 * 实现中国移动的连接器
 * 
 * Revision History
 * 
 * 2006-5-25,star.Zhao,created it
 */
public class CMPPMTConnector extends Connector {

    private Log log = LogFactory.getLog(CMPPMTConnector.class);
    private int START_ACTIVE_TIME = 15 * 1000;

    /**
     * receive synchronized object
     */
    private static Object SYN_RECV_OBJ = new Object();

    /**
     * if have MAX_NULL_TIMES zhe read return null, reConnect !!!
     */
    private int MAX_NULL_TIMES = 5;
    private int NULL_TIME = 0;
    
    /**
     * connect synchronized object
     */
    private static Object SYN_CONN_OBJ = new Object();

    // private int deliverCount = 0;

    private static final int CONNECT_CMPPSMG_SUCCESSFULL = 0;

    public CMPPMTConnector(String aGatewayName, String connName, String aICP_ID,
            String loginName, String aPassword, String aGatewayIP,
            int aGatewayPort, int sVersion, String protcolName) {
        super(aGatewayName, connName, aICP_ID, loginName, aPassword,
                aGatewayIP, aGatewayPort, sVersion, protcolName);
    }

    public boolean writeProtcol(CommonMsgBean obj) throws IOException {
        // log.debug("-----------CMConnector["+this.connName+"].writeProtcol()
        // start send msg！----------");
        boolean result = false;

        // public boolean writeToOut(byte[] b) throws IOException
        if (null != obj && null != obj.getBody()) {
            if (!this.writeToOut(obj.getBody())) {
                log.error(this.connName + " send msg unsuccessfully!");
                result = false;
            } else {
                result = true;
                // log.debug("-----------CMConnector["+this.connName+"].writeProtcol()
                // start send msg successfully！--------");
            }
        } else {
            result = true;
            log.error(this.connName + " send msg unsuccessfully!");
        }
        return result;
    }

    public CommonMsgBean readProtcol() throws IOException {
        CommonMsgBean result = null;
        CMPPMsgHead head = new CMPPMsgHead();
        synchronized (SYN_RECV_OBJ) {
            try {
                head.reada(in);
            } catch (IOException e) { // TODO
                log.error("when read exception:", e);
                NULL_TIME++;
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    log.error("IOException in readProtcol() sleep is Interrupted.");
                }
                //  if max read null re connect
                if (NULL_TIME >= MAX_NULL_TIMES) {
                    this.isConnected = false;
                }
                // 读取失败是应该抛掉
                return result;
            }

            byte[] bodybytes = null;
            if (head.getCommandLength() > CMPPCommon.MSG_HEAD_LENGTH
                    && head.getCommandLength() <= 65535) {
                // MainSystem.logPrint("moReceive4-"
                // +sdf.format(Calendar.getInstance().getTime()));
                bodybytes = new byte[head.getCommandLength()
                        - CMPPCommon.MSG_HEAD_LENGTH];
                in.read(bodybytes);
            }
            // MainSystem.logPrint("moReceive5-"
            // +sdf.format(Calendar.getInstance().getTime()));
            int commandId = head.getCommandID();
            int receiveSequence = head.getSequenceID();
            if (commandId == CMPPCommon.CMPP_ACTIVE_TEST) // 接收到链路激活测试包
            {
                log.debug(this.connName + " recive CMPP_ACTIVE_TEST");
                CMPPActiveTestRep tRep = new CMPPActiveTestRep(receiveSequence);
                try {
                    tRep.write(out);
                } catch (IOException e) {
                    log.error(this.connName
                                    + ".CMPPActiveTestRep write error!");
                }
                log.debug(this.connName + " send CMPP_ACTIVE_TEST_REP ok!");
            } else if (commandId == CMPPCommon.CMPP_ACTIVE_TEST_REP) // 接收到链包
            {
                log.debug(this.connName + " recive CMPP_ACTIVE_TEST_REP");
            } else if (commandId == CMPPCommon.CMPP_TERMINATE) {
                try {
                    CMPPTerminateRep tRep = new CMPPTerminateRep(
                            receiveSequence);
                    tRep.write(out);
                    this.disConnected();
                } catch (IOException e) {
                    this.disConnected();
                    log.error(this.connName
                            + " recive CMPPTerminateRep ,isconnected false", e);
                }
            } else if (commandId == CMPPCommon.CMPP_TERMINATE_REP) {
                this.disConnected();
                log.debug(this.connName + " recive CMPPTerminateRep");
            } else if (commandId == CMPPCommon.CMPP_SUBMIT_REP) {
                // log.debug(this.connName + " recive CMPP_SUBMIT_RESP!");
                // reset SendMT_NoResp_Count
                this.resetSendMTNoRespCount();
                
                result = new CommonMsgBean();
                String gatewayCode = RunnerMgr.getInstance().getGatewayInfo()
                        .getGatewayCode();
                result.setGateWayCode(gatewayCode);
                result.setConnName(this.connName);
                byte[] body = new byte[head.getCommandLength()];
                CMPPCommon.BytesCopy(head.getMsgHead(), body, 0,
                        CMPPCommon.MSG_HEAD_LENGTH - 1, 0);
                CMPPCommon.BytesCopy(bodybytes, body, 0, bodybytes.length - 1,
                        CMPPCommon.MSG_HEAD_LENGTH);
                result.setBody(body);
            } else {
                log.error(this.connName
                        + " recive unkown message! commandId ：[" + commandId
                        + "]");
            }

        }
        return result;
    }

    public boolean checkConnect(String loginName, String password) {
        boolean bOK = false;
        log.debug("Start register " + this.connName + " to SMG！");
        if (null == loginName) {
            log.error("Register " + this.connName + " to SMG！ICP_ID is null");
            return bOK;
        }

        CMPPConnect connect = new CMPPConnect(getSequence(), loginName,
                password, this.version); // int version = 1,没有作用;
        CMPPConnectRep connectRep = new CMPPConnectRep();
        synchronized (SYN_CONN_OBJ) {
            try {
                connect.write(out);
            } catch (IOException e) {
                log.error("-----IOException in " + this.connName
                        + ".write()!---:", e);
            }
            try {
                connectRep.read(in);
            } catch (IOException e) {
                log.error("-----IOException in " + this.connName
                        + " connectResp.read()!---:", e);
            }
        }
        if (connectRep.getStatus() == CONNECT_CMPPSMG_SUCCESSFULL) // Bind正确
        {
            log.debug("Register " + this.connName + " to SMG successfully！");
            bOK = true;
            // 依据下发CMPPActiveTest, 重新连接不用再次启动新ActiveTestThread
            if (!this.isReOpen){
                new CMPPMTActiveTestThread().start();
            }
            
        } else {
            log.error("Register " + this.connName + " to SMG unsuccessfully！");
            bOK = false;
        }
        return bOK;
    }

    /**
     * 链路激活测试
     */
    private class CMPPMTActiveTestThread extends Thread {

        public void run() {
            activeTest();
        }

        public void activeTest() {
            while (true) {
                
                try {
                    Thread.sleep(START_ACTIVE_TIME);
                    
                    if (isClose()) // 重新连接
                    {
                        reOpenConnect();
                    }
                    CMPPActiveTest activeTest = new CMPPActiveTest(
                            getSequence());
                    activeTest.write(out);
                    log.debug(connName + " send CMPP_ACTIVE_TEST OK!");
                    
                } catch (Exception e) {
                    log.error(connName + " send ActiveTest failure. Rebuild the connector!",
                                    e);
                    isConnected = false;
                }
            }
        }
    }
}
